﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using EasierRdp.Controls;
using EasierRdp.Forms;
using EasierRdp.Models;
using EasierRdp.Util;
using MSTSCLib;
using System.Windows.Forms;

namespace EasierRdp.Forms
{
    partial class EasierRdp : Form
    {
        private const string 
            StrConnect = "Connect",
            StrConnectDefaultUser = "Connect with Default User",
            StrConnectDefaultServer = "Connect To Default Server",
            SettingsFile = "EasierRdp.Settings.xml";
        private readonly MultiPagePanel _multiPage = new MultiPagePanel() { Dock = DockStyle.Fill };
        private readonly FullScreenSwitch _fullScreenSwitch;
        private readonly ControlBar _controlBar;

        private static readonly ContextMenu RootMenuStrip = new ContextMenu();
        private static readonly ContextMenu GroupMenuStrip = new ContextMenu();
        private static readonly ContextMenu AllserversMenuStrip = new ContextMenu();
        private static readonly ContextMenu AllUsersStrip = new ContextMenu();
        private static readonly ContextMenu AllSettingsMenuStrip = new ContextMenu();
        private static readonly ContextMenu AllSessionsMenuStrip = new ContextMenu();
        private static readonly ContextMenu ServerMenuStrip = new ContextMenu();
        private static readonly ContextMenu UserMenuStrip = new ContextMenu();
        private static readonly ContextMenu SettingMenuStrip = new ContextMenu();
        private static readonly ContextMenu ServerRefMenuStrip = new ContextMenu();
        private static readonly ContextMenu UserRefMenuStrip = new ContextMenu();
        private static readonly ContextMenu SettingRefMenuStrip = new ContextMenu();
        private static readonly ContextMenu SessionMenuStrip = new ContextMenu();
        private static readonly IDictionary<Type, KeyValuePair<ContextMenu, Image>> ContextMenus = new Dictionary<Type, KeyValuePair<ContextMenu, Image>>()
                    {
                        {typeof(RdpRoot), new KeyValuePair<ContextMenu, Image>(RootMenuStrip, GetResouce("home.png"))},
                        {typeof(RdpGroup), new KeyValuePair<ContextMenu, Image>(GroupMenuStrip, GetResouce("folder.png"))},
                        {typeof(RdpAllServers), new KeyValuePair<ContextMenu, Image>(AllserversMenuStrip, GetResouce("CompMgmt.png"))},
                        {typeof(RdpAllSessions), new KeyValuePair<ContextMenu, Image>(AllSessionsMenuStrip, GetResouce("treeIcon_rdp.png"))},
                        {typeof(RdpAllSettings), new KeyValuePair<ContextMenu, Image>(AllSettingsMenuStrip, GetResouce("ControlPanel.png"))},
                        {typeof(RdpAllUsers), new KeyValuePair<ContextMenu, Image>(AllUsersStrip, GetResouce("group.png"))},
                        {typeof(RdpServer), new KeyValuePair<ContextMenu, Image>(ServerMenuStrip, GetResouce("smallterm.png"))},
                        {typeof(RdpServerRef), new KeyValuePair<ContextMenu, Image>(ServerRefMenuStrip, GetResouce("smallterm.png"))},
                        {typeof(RdpUser), new KeyValuePair<ContextMenu, Image>(UserMenuStrip, GetResouce("user.png"))},
                        {typeof(RdpUserRef), new KeyValuePair<ContextMenu, Image>(UserRefMenuStrip, GetResouce("user.png"))},
                        {typeof(RdpSession), new KeyValuePair<ContextMenu, Image>(SessionMenuStrip, GetResouce("computer_link.png"))},
                        {typeof(RdpSessionRef), new KeyValuePair<ContextMenu, Image>(SessionMenuStrip, GetResouce("computer_link.png"))},
                        {typeof(RdpSetting), new KeyValuePair<ContextMenu, Image>(SettingMenuStrip, GetResouce("computer_security.ico"))},
                        {typeof(RdpSettingRef), new KeyValuePair<ContextMenu, Image>(SettingRefMenuStrip, GetResouce("computer_security.ico"))},
                    };

        private static readonly ImageList _imageList = new ImageList();

        public TreeNode SelectedNode { get; private set; }

        public EasierRdp()
        {
            InitializeComponent();
            RdpMenuStrip.Visible = false;
            MainSplitContainer.Panel2.Controls.Add(_multiPage);
            AllserversMenuStrip.MenuItems.AddRange( new[]{
                new MenuItem("Add Server", EasierRdpEvents.AddServer)
            });
            AllUsersStrip.MenuItems.AddRange( new[]{
                new MenuItem("Add User", EasierRdpEvents.AddUser)
            });
            AllSettingsMenuStrip.MenuItems.AddRange( new[]{
                new MenuItem("Add Setting", EasierRdpEvents.AddSetting)
            });
            AllSessionsMenuStrip.MenuItems.AddRange(new[]{
                new MenuItem("Disconnect All", EasierRdpEvents.DisconnectAllSessions)
            });
            RootMenuStrip.MenuItems.AddRange( new[]{
                new MenuItem("Add Group", EasierRdpEvents.AddGroup)
            });
            GroupMenuStrip.MenuItems.AddRange(new[]{
                new MenuItem("Edit", EasierRdpEvents.EditGroup),
                new MenuItem("Remove", EasierRdpEvents.RemoveGroup),
                new MenuItem("Choose Server", EasierRdpEvents.AddServerRef),
                new MenuItem("Choose User", EasierRdpEvents.AddUserRef),
                new MenuItem("Add Group", EasierRdpEvents.AddGroup),
            });
            ServerMenuStrip.MenuItems.AddRange(new[]{
                new MenuItem(StrConnectDefaultUser, EasierRdpEvents.ConnectWithDefault),
                new MenuItem("Edit", EasierRdpEvents.EditServer),
                new MenuItem("Choose User", EasierRdpEvents.AddUserRef),
                new MenuItem("Remove", EasierRdpEvents.RemoveServer),
            });
            UserMenuStrip.MenuItems.AddRange(new[]{
                new MenuItem(StrConnectDefaultServer, EasierRdpEvents.ConnectWithDefault),
                new MenuItem("Edit", EasierRdpEvents.EditUser),
                new MenuItem("Choose Server", EasierRdpEvents.AddServerRef),
                new MenuItem("Remove", EasierRdpEvents.RemoveUser),
            });
            SessionMenuStrip.MenuItems.AddRange(new[]{
                new MenuItem("Disconnect", EasierRdpEvents.DisconnectSession), 
                new MenuItem("Reconnect", EasierRdpEvents.Connect), 
            });
            SettingMenuStrip.MenuItems.AddRange(new[]{
                new MenuItem("Edit", EasierRdpEvents.EditSetting), 
                new MenuItem("Remove", EasierRdpEvents.RemoveSetting),
            });
            ServerRefMenuStrip.MenuItems.AddRange(new[]{
                new MenuItem(StrConnect, EasierRdpEvents.Connect),
                new MenuItem("Remove", EasierRdpEvents.RemoveServerRef),
            });
            UserRefMenuStrip.MenuItems.AddRange(new[]{
                new MenuItem(StrConnect, EasierRdpEvents.Connect),
                new MenuItem("Remove", EasierRdpEvents.RemoveUserRef),
            });
            SettingRefMenuStrip.MenuItems.AddRange(new[]{
                new MenuItem("SetDefault", EasierRdpEvents.Connect), 
            });
            if (!File.Exists(SettingsFile))
            {
                var file = File.Create(SettingsFile);
                file.Close();
            }
            EasierRdpEvents.MainForm = this;
            _fullScreenSwitch = new FullScreenSwitch(this);
            _controlBar = new ControlBar(this) {TopLevel = false, Left = 300};
            Controls.Add(_controlBar);
        }

        private void toolStripButton1_Click(object sender, EventArgs e)
        {
            MessageBox.Show(SkyDrive.SkyDriveClient.method());
        }

        private void MainForm_Load(object sender, EventArgs e)
        {
            foreach (var item in ContextMenus)
            {
                _imageList.Images.Add(item.Key.ToString(), item.Value.Value);
            }
            RdpTreeView.ImageList = _imageList;
            RdpContext.RdpRoot = new RdpRoot(SettingsFile);
            MainSplitContainer.SplitterDistance = RdpContext.RdpRoot.TreeViewWidth;
            EasierRdp_Resize(this, null);
            RebindTree();
        }

        private static TreeNode GetTreeView(INode node)
        {
            var n = new TreeNode(node.Name, node.Children.Select(GetTreeView).ToArray());
            if (node.Expanded)
            {
                n.ExpandAll();
            }
            else
            {
                n.Collapse();
            }
            n.Tag = node;
            var resource = ContextMenus[node.GetType()];
            n.ContextMenu = resource.Key;
            n.ImageKey = n.SelectedImageKey = n.StateImageKey = node.GetType().ToString();
            foreach (MenuItem menuItem in n.ContextMenu.MenuItems)
            {
                if (menuItem.Text == StrConnect || menuItem.Text == StrConnectDefaultServer || menuItem.Text == StrConnectDefaultUser)
                {
                    EventHandler handler = EasierRdpEvents.ConnectWithSetting;
                    if (menuItem.Text != StrConnect)
                    {
                        handler = EasierRdpEvents.ConnectWithDefault;
                    }
                    menuItem.MenuItems.Clear();
                    foreach (var setting in RdpContext.Settings.Values)
                    {
                        var index = menuItem.MenuItems.Add(new MenuItem(setting.Name, handler));
                        menuItem.MenuItems[index].Tag = setting;
                    }
                }
            }
            return n;
        }

        public void RebindTree()
        {
            RdpTreeView.Nodes.Clear();
            RdpTreeView.Nodes.Add(GetTreeView(RdpContext.RdpRoot));
            _controlBar.Rebind();
        }

        public void AddSession(RdpSession session)
        {
            _multiPage.AddPage(session.Container);
            session.RequestExitFullScreen += RequestExitFullScreen;
            session.RequestMiniSize += RequestMiniSize;
            _controlBar.SetActiveSession(session);
        }

        public void ToolStripFullScreen_Click(object sender, EventArgs e)
        {
            _controlBar.Hide();
            _fullScreenSwitch.FullScreen = !_fullScreenSwitch.FullScreen; 
            if (_fullScreenSwitch.FullScreen)
            {
                _controlBar.Show();
                _controlBar.BringToFront();
            }
            var width = _multiPage.Width;
            if (RdpContext.FrontSession != null)
            {
                _controlBar.SetActiveSession(RdpContext.FrontSession);
                width = RdpContext.FrontSession.Width;
            }
            _controlBar.Left = (width - _controlBar.Width) / 2;
        }

        private void RdpTreeView_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
        {
            SelectedNode = e.Node;
            e.Node.ImageKey = e.Node.Tag.GetType().ToString();
        }

        private void RdpTreeView_NodeMouseDoubleClick(object sender, TreeNodeMouseClickEventArgs e)
        {
            var rdpSession = e.Node.Tag as RdpSession;
            if (rdpSession != null)
            {
                rdpSession.Show();
                _controlBar.SetActiveSession(rdpSession);
            }
        }

        private static Image GetResouce(string fileName)
        {
            var assem = typeof(EasierRdp).Assembly;
            using(var stream = assem.GetManifestResourceStream("EasierRdp.Resources." + fileName))
            {
                if (stream != null)
                {
                    return Image.FromStream(stream);
                }
            }
            return null;
        }

        private void RequestExitFullScreen(object sender, EventArgs e)
        {
            _fullScreenSwitch.FullScreen = false;
        }

        private void RequestMiniSize(object sender, EventArgs e)
        {
            WindowState = FormWindowState.Minimized;
        }

        internal class FullScreenSwitch
        {
            private readonly EasierRdp _mainForm;
            private Boolean _fullScreen;

            internal FullScreenSwitch(EasierRdp mainForm)
            {
                this._mainForm = mainForm;
            }

            internal bool FullScreen
            {
                get
                {
                    return this._fullScreen;
                }
                set
                {
                    SwitchFullScreen(value);
                }
            }

            private void SwitchFullScreen(Boolean newfullScreen)
            {
                _mainForm.SuspendLayout();
                this.SetFullScreen(newfullScreen);
                this._fullScreen = newfullScreen;
                _mainForm.ResumeLayout();
            }

            private void SetFullScreen(Boolean fullScreen)
            {
                _mainForm.Visible = false;
                HideToolBar(fullScreen);

                if (fullScreen)
                {
                    this._mainForm.FormBorderStyle = FormBorderStyle.None;
                    this._mainForm.WindowState = FormWindowState.Normal;
                    var screenBounds = Screen.FromControl(this._mainForm._multiPage).Bounds;
                    this._mainForm.Width = screenBounds.Width;
                    this._mainForm.Location = screenBounds.Location;
                    this._mainForm.Height = Screen.FromControl(this._mainForm._multiPage).Bounds.Height;
                    this._mainForm.BringToFront();
                }
                else
                {
                    this._mainForm.FormBorderStyle = FormBorderStyle.Sizable;
                }
                _mainForm.Visible = true;
                _mainForm.PerformLayout();
            }

            private void HideToolBar(Boolean fullScreen)
            {
                if (fullScreen)
                {
                    _mainForm._multiPage.Parent = _mainForm;
                    _mainForm._multiPage.BringToFront();
                    _mainForm._multiPage.Focus();
                }
                else
                {
                    _mainForm._multiPage.Parent = _mainForm.MainSplitContainer.Panel2;
                }
                _mainForm.BringToFront();
                _mainForm.Focus();
                _mainForm.RdpToolStrip.Visible =
                _mainForm.RdpStatusStrip.Visible = !fullScreen;
            }
        }

        private void RdpTreeView_AfterExpand(object sender, TreeViewEventArgs e)
        {
            ((INode)e.Node.Tag).Expanded = true;
        }

        private void RdpTreeView_AfterCollapse(object sender, TreeViewEventArgs e)
        {
            ((INode) e.Node.Tag).Expanded = false;
        }

        private void EasierRdp_FormClosed(object sender, FormClosedEventArgs e)
        {
            RdpContext.RdpRoot.TreeViewWidth = MainSplitContainer.SplitterDistance;
            RdpContext.RdpRoot.SaveSettings();
        }

        private void EasierRdp_Resize(object sender, EventArgs e)
        {
            this.MainSplitContainer.Panel1MinSize = 160;
            if (this.MainSplitContainer.Width > 200)
            {
                this.MainSplitContainer.Panel2MinSize = this.MainSplitContainer.Width - 200;
            }
        }
    }
}
